#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

/*
1、栈只能从一端（栈顶）存取，另一端（栈底）是封闭的
2、在栈中，都必须从栈顶存取数据，且遵循  先进后出 原则
栈是一种只能从表的一端存取数据，且遵循 先进后出 原则的线性存储结构

入栈和出栈

入栈：将数据存储到栈里面去
出栈：将数据从站里面取出来

栈：特殊的线性存储结构
顺序表
链表

栈的应用


链表栈：会将链表的头节点作为栈顶，尾节点作为栈底
目的：减少链表的遍历从而提高效率


*/

//节点
typedef struct Node
{
    int data;
    struct Node* pnext;
}Node;

//一 元素入栈
//参数：头指针，数据
//返回值：头指针
Node* push(Node* stack,int a)
{
    printf("push stack:%x\n",stack);
    //1.申请内存
    Node* newNode=(Node*)malloc(sizeof(Node));
    printf("push newNode:%x\n",newNode);
    //2.数据域给值
    newNode->data=a;
    //3.把申请的节点作为头节点
    newNode->pnext=stack;
    printf("push newNode :%d %x\n",newNode->data,newNode->pnext);
    printf("push1 stack:%x\n",stack);
    //4.头指针指向新的头节点
    stack=newNode;
    printf("push2 stack:%x\n",stack);
    //5.返回头指针
    return stack;
}


//二 元素出栈
//参数：头指针
//返回值：头指针
Node* pop(Node* stack)
{
    //判断栈里面是否有为空
    if(stack)
    {
        //1.准备临时指针保存栈顶
        Node* p=stack;
        //2.头指针后移
        stack=stack->pnext;
        //3.打印当前出栈元素
        printf("pop now value:%d ",p->data);
        //4.再次判断是否到了栈底
        if(stack)
        {
            printf("pop now top value:%d\n",stack->data);
        }
        else
        {
            printf("pop is null\n");
        }
        //3.释放原来的头节点
        free(p);
    }
    else
    {
        printf("kong zhan!\n");
    }
    return stack;
}

int main()
{
    Node* stack=NULL;
    Node n;
    printf("%d\n",sizeof(n));
    printf("%d\n",sizeof(n.data));
    printf("%d\n",sizeof(n.pnext));
    //入栈
    stack=push(stack,1);
    stack=push(stack,2);
    stack=push(stack,3);
    stack=push(stack,4);
    stack=push(stack,5);
    
    //出栈
    stack=pop(stack);
    stack=pop(stack);
    stack=pop(stack);
    stack=pop(stack);
    stack=pop(stack);
    stack=pop(stack);



	//system("pause");
	return 0;
} 